package com.googlecode.proxjed;

import com.google.common.base.Predicate;
import com.googlecode.recycled.lang.assertions.Assert;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public abstract class Proxy<T> implements MethodInterceptor {

    protected T instance;

    protected Class<T> type;

    protected Predicate<Method> joinPoint;

    public Proxy(T instance, Class<T> type, Predicate<Method> joinPoint) {
        this.instance = instance;
        this.type = Assert.notNull(type);
        this.joinPoint = joinPoint;
    }

    @SuppressWarnings("unchecked")
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if (joinPoint == null || joinPoint.apply(method)) {
            return doIntercept((T) o, method, objects, methodProxy);
        }
        return method.invoke(instance, objects);
    }

    public abstract Object doIntercept(T o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable;

}
